home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / icmpcmd.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  5KB  |  226 lines

  1. /* ICMP-related user commands */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "icmp.h"
  5. #include "mbuf.h"
  6. #include "netuser.h"
  7. #include "internet.h"
  8. #include "timer.h"
  9. #include "ping.h"
  10.  
  11. int
  12. doicmpstat()
  13. {
  14.     extern struct icmp_errors icmp_errors;
  15.     extern struct icmp_stats icmp_stats;
  16.     extern char *icmptypes[];
  17.     register int i;
  18.  
  19.     printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
  20.      icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
  21.      icmp_errors.bdcsts);
  22.     printf("type  rcvd  sent\n");
  23.     for(i=0;i<ICMP_TYPES;i++){
  24.         if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
  25.             continue;
  26.         printf("%-6u%-6u%-6u",i,icmp_stats.input[i],
  27.             icmp_stats.output[i]);
  28.         if(icmptypes[i] != NULLCHAR)
  29.             printf("  %s",icmptypes[i]);
  30.         printf("\n");
  31.     }
  32.     return 0;
  33. }
  34.  
  35. /* Hash table list heads */
  36. struct ping *ping[PMOD];
  37.  
  38. /* Counter for generating seq numbers */
  39. static int16 iclk;
  40.  
  41. /* Increment counter -- called by low level clock tick */
  42. icmpclk()
  43. {
  44.     iclk++;
  45. }
  46.  
  47. /* Send ICMP Echo Request packets */
  48. doping(argc,argv)
  49. int argc;
  50. char *argv[];
  51. {
  52.     int32 dest;
  53.     struct ping *add_ping(),*pp1;
  54.     register struct ping *pp;
  55.     void ptimeout();
  56.     int16 hval,hash_ping();
  57.     int i;
  58.     char *inet_ntoa();
  59.  
  60.     if(argc < 2){
  61.         printf("Host                Sent    Rcvd   %%   Avg RTT  Interval\n");
  62.         for(i=0;i<PMOD;i++){
  63.             for(pp = ping[i];pp != NULLPING;pp = pp->next){
  64.                 printf("%-16s",inet_ntoa(pp->remote));
  65.                 printf("%8lu%8lu",pp->count,pp->echoes);
  66.                 printf("%4lu%10lu%10lu\n",
  67.                  (long)pp->echoes * 100 / pp->count,
  68.                  pp->echoes != 0 ? 
  69.                  (long)pp->ttotal * MSPTICK / pp->echoes : 0,
  70.                  ((long)pp->timer.start * MSPTICK + 500) / 1000);
  71.             }
  72.         }
  73.         return 0;
  74.     }
  75.     if(strcmp(argv[1],"clear") == 0){
  76.         for(i=0;i<PMOD;i++){
  77.             for(pp = ping[i];pp != NULLPING;pp = pp1){
  78.                 pp1 = pp->next;
  79.                 del_ping(pp);
  80.             }
  81.         }
  82.         return 0;
  83.     }
  84.     if((dest = resolve(argv[1])) == 0){
  85.         printf("Host %s unknown\n",argv[1]);
  86.         return 1;
  87.     }
  88.     /* See if dest is already in table */
  89.     hval = hash_ping(dest);
  90.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next){
  91.         if(pp->remote == dest){
  92.             break;
  93.         }
  94.     }
  95.     if(argc > 2){
  96.         /* Inter-ping time is specified; set up timer structure */
  97.         if(pp == NULLPING)
  98.             pp = add_ping(dest);
  99.         pp->timer.start = atoi(argv[2]) * (1000.0 / MSPTICK);
  100.         pp->timer.func = ptimeout;
  101.         pp->timer.arg = (char *)pp;
  102.         pp->remote = dest;
  103.         start_timer(&pp->timer);
  104.         pp->count++;
  105.         (void)pingem(dest,iclk,REPEAT);
  106.     } else
  107.         (void)pingem(dest,iclk,ONESHOT);
  108.  
  109.     return 0;
  110. }
  111.  
  112. /* Called by ping timeout */
  113. void
  114. ptimeout(p)
  115. char *p;
  116. {
  117.     register struct ping *pp;
  118.  
  119.     /* Send another ping */
  120.     pp = (struct ping *)p;
  121.     pp->count++;
  122.     (void)pingem(pp->remote,iclk,REPEAT);
  123.     start_timer(&pp->timer);
  124. }
  125. /* Send ICMP Echo Request packet */
  126. static
  127. pingem(dest,seq,id)
  128. int32 dest;
  129. int16 seq;
  130. int16 id;
  131. {
  132.     struct mbuf *bp,*htonicmp();
  133.     struct icmp icmp;
  134.     extern struct icmp_stats icmp_stats;
  135.  
  136.     icmp_stats.output[ECHO]++;
  137.     icmp.type = ECHO;
  138.     icmp.code = 0;
  139.     icmp.args.echo.seq = seq;
  140.     icmp.args.echo.id = id;
  141.     if((bp = htonicmp(&icmp,NULLBUF)) == NULLBUF)
  142.         return 0;
  143.     return ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
  144. }
  145.  
  146. /* Called with incoming Echo Reply packet */
  147. /*ARGSUSED*/
  148. int
  149. echo_proc(source,dest,icmp)
  150. int32 source,dest;
  151. struct icmp *icmp;
  152. {
  153.     register struct ping *pp;
  154.     int16 hval,hash_ping();
  155.     int16 rtt;
  156.     char *inet_ntoa();
  157.  
  158.     rtt = iclk - icmp->args.echo.seq;
  159.     hval = hash_ping(source);
  160.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
  161.         if(pp->remote == source)
  162.             break;
  163.     if(pp == NULLPING || icmp->args.echo.id != 1){
  164.         printf("%s: echo reply id %u seq %u, %lu ms\n",
  165.          inet_ntoa(source),
  166.          icmp->args.echo.id,icmp->args.echo.seq,
  167.          (long)rtt * MSPTICK);
  168.          fflush(stdout);
  169.     } else {
  170.         /* Repeated poll, just keep stats */
  171.         pp->ttotal += rtt;
  172.         pp->echoes++;
  173.     }
  174. }
  175. static
  176. int16
  177. hash_ping(dest)
  178. int32 dest;
  179. {
  180.     int16 hval;
  181.  
  182.     hval = (hiword(dest) ^ loword(dest)) % PMOD;
  183.     return hval;
  184. }
  185. /* Add entry to ping table */
  186. static
  187. struct ping *
  188. add_ping(dest)
  189. int32 dest;
  190. {
  191.     struct ping *pp;
  192.     int16 hval,hash_ping();
  193.  
  194.     pp = (struct ping *)calloc(1,sizeof(struct ping));
  195.     if(pp == NULLPING)
  196.         return NULLPING;
  197.  
  198.     hval = hash_ping(dest);
  199.     pp->prev = NULLPING;
  200.     pp->next = ping[hval];
  201.     if(pp->next != NULLPING)
  202.         pp->next->prev = pp;
  203.     ping[hval] = pp;
  204.     return pp;
  205. }
  206. /* Delete entry from ping table */
  207. static
  208. del_ping(pp)
  209. struct ping *pp;
  210. {
  211.     int16 hval,hash_ping();
  212.  
  213.     stop_timer(&pp->timer);
  214.  
  215.     if(pp->next != NULLPING)
  216.         pp->next->prev = pp->prev;
  217.     if(pp->prev != NULLPING) {
  218.         pp->prev->next = pp->next;
  219.     } else {
  220.         hval = hash_ping(pp->remote);
  221.         ping[hval] = pp->next;
  222.     }
  223.     free((char *)pp);    
  224. }
  225.  
  226.